package cn.tedu.charging.cost.service.impl;

import cn.tedu.charging.common.pojo.param.ChargingProcessParam;
import cn.tedu.charging.common.pojo.vo.ChargingProcessVO;
import cn.tedu.charging.cost.dao.repository.ChargingCostESPORepository;
import cn.tedu.charging.cost.dao.repository.ChargingCostRuleCachRepository;
import cn.tedu.charging.cost.dao.repository.ChargingCostRuleRepository;
import cn.tedu.charging.cost.dao.repository.ChargingGunInfoRepository;
import cn.tedu.charging.cost.entity.po.ChargingCostRulePO;
import cn.tedu.charging.cost.entity.po.ChargingDataESPO;
import cn.tedu.charging.cost.service.CostService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;


@Slf4j
@Service
public class CostServiceImpl implements CostService {

    @Autowired
    private ChargingCostRuleRepository chargingCostRuleRepository;
    @Autowired
    private ChargingGunInfoRepository chargingGunInfoRepository;

    @Autowired
    private ChargingCostESPORepository chargingCostESPORepository;


    @Override
    public ChargingProcessVO cacleChargingPrice(ChargingProcessParam chargingProcessParam) {
        log.debug("开始计算充电价格 chargingProcessParam = {}",chargingProcessParam);
        ChargingProcessVO chargingProcessVO = new ChargingProcessVO();
        //获取枪的类型
        Integer gunType = chargingGunInfoRepository.getGunType(chargingProcessParam.getGunId());
        //获取定价规则
        ChargingCostRulePO chargingCostRulePO = getChargingCostRulePO(chargingProcessParam,gunType);
        log.debug("获取到的充电规则为 chargingCostRulePO = {}",chargingCostRulePO);
        if (chargingCostRulePO != null) {
            //获取本次价格
            BigDecimal price = getPrice(chargingProcessParam.getOrderNo(),chargingProcessParam.getChargingDushu(), chargingCostRulePO.getPowerFee());
            //价格计算完成 保存数据
            ChargingDataESPO chargingDataESPO = saveChargingData(chargingProcessParam, price);
            log.debug("当前充电的电量为 {}，本次充电的价格为 {}，目前总价为 {}",chargingDataESPO.getChargingDushu(),price,chargingDataESPO.getTotalPrice());
            log.debug("chargingDataESPO = {}" ,chargingDataESPO);

            BeanUtils.copyProperties(chargingDataESPO,chargingProcessVO);
            //计算总花费时间 赋值
            chargingProcessVO.setTotalTime(chargingDataESPO.costTime(System.currentTimeMillis()));

        } else {
            log.debug("本次没有查询到对应的计价规则！");
        }

        return chargingProcessVO;
    }

    /**
     * 保存本次数据
     * @param chargingProcessParam
     * @param price
     */
    private ChargingDataESPO saveChargingData(ChargingProcessParam chargingProcessParam,BigDecimal price) {
        Optional<ChargingDataESPO> byId = chargingCostESPORepository.findById(chargingProcessParam.getOrderNo());

        //判断是否是第一次
        if (!byId.isPresent()){
           return saveFirstChargingData(chargingProcessParam,price);
        }else {
            ChargingDataESPO chargingDataESPO = byId.get();
            chargingDataESPO.addPrice(price);
            chargingDataESPO.countAdd1();
            chargingDataESPO.setChargingDushu(chargingProcessParam.getChargingDushu());
            chargingCostESPORepository.save(chargingDataESPO);
            return chargingDataESPO;
        }
    }

    /**
     * 保存第一次的数据
     * @param chargingProcessParam
     * @param price
     */
    private ChargingDataESPO saveFirstChargingData(ChargingProcessParam chargingProcessParam, BigDecimal price) {
        //保存数据
        ChargingDataESPO chargingDataESPO = new ChargingDataESPO();
        //订单号
        chargingDataESPO.setOrderNo(chargingProcessParam.getOrderNo());
        //充电电量
        chargingDataESPO.setChargingDushu(chargingProcessParam.getChargingDushu());
        //总价格
        chargingDataESPO.setTotalPrice(price);
        //充电次数
        chargingDataESPO.setCount(1);
        //开始时间
        chargingDataESPO.setStartTime(System.currentTimeMillis());
        //用户id
        chargingDataESPO.setUserId(chargingProcessParam.getUserId());
        //枪id
        chargingDataESPO.setGunId(chargingProcessParam.getGunId());

        chargingCostESPORepository.save(chargingDataESPO);
        return chargingDataESPO;
    }


    /**
     * 计算本次价格
     * @param orderNo
     * @param chargingDushu
     * @param powerFee
     * @return
     */
    private BigDecimal getPrice(String orderNo,Float chargingDushu, BigDecimal powerFee) {
        //获取本次的价格
        Optional<ChargingDataESPO> optional = chargingCostESPORepository.findById(orderNo);
        if (optional.isPresent()){
            ChargingDataESPO chargingDataESPO = optional.get();
            Float diffDuShu = chargingDushu-chargingDataESPO.getChargingDushu();
            return powerFee.multiply(new BigDecimal(diffDuShu));
        }
        return powerFee.multiply(new BigDecimal(chargingDushu));
    }


    /**
     * 获取对应的计价规则
     * @param chargingProcessParam
     * @param gunType
     * @return
     */
    private ChargingCostRulePO getChargingCostRulePO(ChargingProcessParam chargingProcessParam,Integer gunType) {
        Integer hour = LocalDateTime.now().getHour();
        List<ChargingCostRulePO> listRules=getRules(chargingProcessParam);
        log.debug("充电站id = {} 充电规则s是 {}",chargingProcessParam.getStationId(),listRules);

        for (ChargingCostRulePO chargingCostRulePO :listRules){
            if (hour >= chargingCostRulePO.getStartTime() && hour < chargingCostRulePO.getEndTime() && gunType.equals(chargingCostRulePO.getGunType())){
                return chargingCostRulePO;
            }
        }
        return null;
    }



    @Autowired
    private ChargingCostRuleCachRepository chargingCostRuleCachRepository;
    /**
     * 获取本充电站的所有规则
     * @param chargingProcessParam
     * @return
     */
    private List<ChargingCostRulePO> getRules(ChargingProcessParam chargingProcessParam) {
        Long startTime = System.currentTimeMillis();
        List<ChargingCostRulePO> rulesByStationId = chargingCostRuleCachRepository.getRulesByStationId(chargingProcessParam);
        Long endTime = System.currentTimeMillis();
        log.debug("花费时间：{} 毫秒",endTime-startTime);

        return rulesByStationId;
    }
}
